import threading
import queue
import time
from create_app import db,User,app,cfg

import uuid
def TaskFunction(func):
    def create_time_sleep_func(evt):
        def time_sleep(_time):
            for _ in range(_time):
                if evt.is_set():
                    return
                time.sleep(1)
        return time_sleep
                
    def wrapper(*args,**kargs):
        kargs['time_sleep'] = create_time_sleep_func(kargs.get('evt'))
        return func(*args,**kargs)
    return wrapper
class TaskScheduling:
    def __init__(self):
        self.board_task_map = {}
        self.task_id_stop_evt_map = {}
        self.ne_map = {}
    def add_task(self,ip_board_key,task,**kargs):
        if not self.board_task_map.get(ip_board_key):
            self.board_task_map[ip_board_key] = ThreadPool(num_threads=1)
            self.board_task_map[ip_board_key].start()
        evt = threading.Event()
        task_id = str(uuid.uuid4())
        user = User(task_id=task_id,status=cfg.TASK_STATUS_WAITING)
        db.session.add(user)
        db.session.commit()
        self.board_task_map.get(ip_board_key).add_task(task=task, task_id=task_id,evt=evt,**kargs)
        self.task_id_stop_evt_map[task_id] = evt
    def stop_task(self,task_id):
        evt = self.task_id_stop_evt_map.get(task_id)
        if evt:
            evt.set()
            self.task_id_stop_evt_map.pop(task_id)
    def batch_add_task(self,task,task_params):
        for task_param in task_params:
            ip_board_key = task_param.get('ip_board_key')
            params = task_param.get('params')
            self.add_task(ip_board_key,task,**params)


class ThreadPool:
    def __init__(self, num_threads=1):
        self.tasks = queue.Queue()  
        self.num_threads = num_threads
        self.threads = []  

    def worker(self):
        while True:
            task, args, kwargs = self.tasks.get()
            if task is None:  
                break
            try:
                with app.app_context():
                    task(*args, **kwargs)  
            except Exception as e:
                print(f"Error executing task: {e}")
            self.tasks.task_done()  

    def add_task(self, task, *args, **kwargs):
        """添加任务到队列"""
        self.tasks.put((task, args, kwargs))

    def start(self):
        """启动线程池"""
        for _ in range(self.num_threads):
            thread = threading.Thread(target=self.worker)
            thread.daemon = True  
            thread.start()
            self.threads.append(thread)

    def wait_for_completion(self):
        """等待所有任务完成"""
        self.tasks.join() 

    def stop(self):
        """停止线程池"""
        for _ in range(self.num_threads):
            self.add_task(None)  
        for thread in self.threads:
            thread.join()  


# 示例任务
@TaskFunction
def example_task(name,**kargs):
    time_sleep = kargs.get('time_sleep')
    sleep_time = kargs.get('sleep_time')
    task_id = kargs['task_id']
    print(f"Task {task_id} starting.")
    user = User.query.filter_by(task_id=task_id).first()
    user.status = cfg.TASK_STATUS_RUNNING
    db.session.commit()
    print(name)
    time_sleep(sleep_time)
    print(f"Task {task_id} finished after {sleep_time} seconds.")

